'use strict';

import GlobalConstant from './GlobalConstant.js';
import BMap from 'BMap';
import {LOCATION} from '../vuex/mutations-types';

let instance = null;

class LocationManager {
  static defaultLocation = {
    latitude: 31.237037783,
    longitude: 121.4834974484,
    hasLocation: false
  };

  static defaultLocationCity = {
    id: 2,
    name: '上海',
    address: '上海市黄浦区福州路117号',
    hasLocationCity: false
  };

  constructor() {
    if (!instance) {
      instance = this;
      global.locationCallback = this.locationCallback.bind(this);
      this.nativeLocationCallback = null;
    }
    return instance;
  }

  static defaultManager() {
    return new LocationManager();
  }

  locationCallback(param) {
    if (this.nativeLocationCallback) {
      this.nativeLocationCallback(param);
    }
  }

  getLocation() {
    return new Promise((resolve, reject) => {
      Promise.race([this.appLocationTimeOutPromise(1000), this.getNativeLocation()]).then(location => {
        let longitude = null
        let latitude = null
        if (!this.nativeLocationNull(location)) {
          longitude = location.longitude
          latitude = location.latitude
        }
        this.handleLocationPromise(longitude, latitude).then(location => {
          this.updateLocationStore(location)
          resolve(location)
        }, error => {
          this.updateLocationStore()
          reject(error)
        }).catch(error => {
          console.log(error);
        })
      })
    });
  }

  /**
   * 定位处理回调
   * @param longitude 定位到得经纬度
   * @param latitude 定位到的经纬度
   */
  handleLocationPromise (longitude, latitude) {
    if (longitude && latitude) {
      return new Promise((resolve, reject) => {
        resolve({longitude, latitude})
      })
    } else {
      return new Promise((resolve, reject) => {
        this.baiduLocatePromise().then(location => {
          resolve(location)
        }, error => {
          reject(error)
        })
      })
    }
  }

  /**
   * 原生定位
   * @returns {Promise}
   */
  getNativeLocation() {
    return new Promise((resolve, reject) => {
      this.nativeLocationCallback = (location) => {
        resolve(location)
      }
      // global.bcmLocation()
    })
  }

  /**
   * 百度定位
   */
  baiduLocatePromise () {
    return new Promise((resolve, reject) => {
      // 开始百度定位
      let geolocation = new BMap.Geolocation()
      geolocation.getCurrentPosition((options) => {
          if (geolocation.getStatus() === 0 && options.accuracy !== null) {
            resolve(options)
          } else {
            reject()
          }
        },
        () => {
          reject()
        },
        {timeout: 2000, maximumAge: 0})
    })
  }

  /**
   * 更新location Vuex
   * @param location
   */
  updateLocationStore (location) {
    if (location) {
      this._hasLocation = true
      GlobalConstant.store.commit(LOCATION.UPDATE_LOCATION, {
        latitude: location.latitude,
        longitude: location.longitude,
        hasLocation: true
      })
    } else {
      this._hasLocation = false
      GlobalConstant.store.commit(LOCATION.UPDATE_LOCATION)
    }
  }

  /**
   * app定位超时处理
   */
  appLocationTimeOutPromise(timeout) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({longitude: null, latitude: null})
      }, timeout)
    })
  }

  /**
   * 判断原生回调是否为null
   * @param location
   * @returns {boolean}
   */
  nativeLocationNull (location) {
    if (!location) {
      return true
    }
    if (!location.hasOwnProperty('longitude') || !location.hasOwnProperty('latitude')) {
      return true
    }
    if (location.longitude === '(null)' || location.latitude === '(null)') {
      return true
    }
    return false
  }
}

export default LocationManager;
